package org.boot.fast.repository;

import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.boot.fast.pojo.QueryCondition;
import org.boot.fast.util.CollUtil;
import org.boot.fast.util.MappingUtil;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 数据库操作工具类，提供数据库表的增删改查相关的静态方法(JdbcTemplate实现)
 * @author: 最爱芫荽
 * @email: 15733440205@163.com
 */
public class JdbcRepositoryUtil {

    private static JdbcTemplate jdbcTemplate;

    static {
        jdbcTemplate = SpringUtil.getBean(JdbcTemplate.class);
    }

    /**
     * 插入数据
     * @param table 表名
     * @param dataMap 字段名和值的映射
     * @return 影响的行数
     */
    public static int insert(String table, Map<String, Object> dataMap) {
        if (dataMap == null || dataMap.isEmpty()) {
            throw new IllegalArgumentException("插入数据不能为空");
        }

        StringBuilder sql = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        StringBuilder values = new StringBuilder();
        List<Object> params = new ArrayList<>();

        sql.append("INSERT INTO ").append(table).append(" (");

        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
            columns.append(entry.getKey()).append(",");
            values.append("?,");
            params.add(entry.getValue());
        }

        // 去除最后一个逗号
        columns.setLength(columns.length() - 1);
        values.setLength(values.length() - 1);

        sql.append(columns).append(") VALUES (").append(values).append(")");

        return jdbcTemplate.update(sql.toString(), params.toArray());
    }

    /**
     * 通用插入并返回主键
     * @param table   表名
     * @param dataMap 字段-值
     * @return 主键值（MySQL 自增或 KingBase 序列均适用）
     */
    public static Long insertBack(String table, Map<String, Object> dataMap) {
        if (dataMap == null || dataMap.isEmpty()) {
            throw new IllegalArgumentException("插入数据不能为空");
        }

        /* ---------- 1. 组装 INSERT ---------- */
        StringBuilder sql = new StringBuilder("INSERT INTO ")
                .append(table).append(" (");

        StringBuilder placeholders = new StringBuilder();
        List<Object> params = new ArrayList<>(dataMap.size());

        for (Map.Entry<String, Object> e : dataMap.entrySet()) {
            sql.append(e.getKey()).append(',');
            placeholders.append("?,");
            params.add(e.getValue());
        }
        sql.setLength(sql.length() - 1);            // 去掉最后一个 ,
        placeholders.setLength(placeholders.length() - 1);

        sql.append(") VALUES (").append(placeholders).append(')');

        /* ---------- 2. 使用 JdbcTemplate 的 KeyHolder ---------- */
        KeyHolder holder = new GeneratedKeyHolder();

        jdbcTemplate.update(connection -> {
            PreparedStatement ps = connection
                    .prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS);
            for (int i = 0; i < params.size(); i++) {
                ps.setObject(i + 1, params.get(i));
            }
            return ps;
        }, holder);
        //转Long
        return holder.getKey().longValue();
    }




    /**
     * 根据ID删除数据
     * @param table 表名
     * @param id 主键值
     * @return 影响的行数
     */
    public static int deleteById(String table, Object id) {
        String sql = "DELETE FROM " + table + " WHERE id = ?";
        return jdbcTemplate.update(sql, id);
    }

    /**
     * 根据条件删除数据
     * @param table 表名
     * @param conditions 条件列表
     * @return 影响的行数
     */
    public static int delete(String table, List<QueryCondition> conditions) {
        if (conditions == null || conditions.isEmpty()) {
            throw new IllegalArgumentException("删除条件不能为空");
        }

        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM ").append(table);

        QueryBuilderResult result = buildWhereClause(conditions);
        sql.append(result.getWhereClause());

        return jdbcTemplate.update(sql.toString(), result.getParams().toArray());
    }

    /**
     * 根据ID更新数据
     * @param table 表名
     * @param dataMap 要更新的字段和值
     * @param id 主键值
     * @return 影响的行数
     */
    public static int updateById(String table, Map<String, Object> dataMap, Object id) {
        if (dataMap == null || dataMap.isEmpty()) {
            throw new IllegalArgumentException("更新数据不能为空");
        }

        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE ").append(table).append(" SET ");
        List<Object> params = new ArrayList<>();

        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
            sql.append(entry.getKey()).append(" = ?,");
            params.add(entry.getValue());
        }

        // 去除最后一个逗号
        sql.setLength(sql.length() - 1);
        sql.append(" WHERE id = ?");
        params.add(id);

        return jdbcTemplate.update(sql.toString(), params.toArray());
    }

    /**
     * 根据条件更新数据
     * @param table 表名
     * @param dataMap 要更新的字段和值
     * @param conditions 条件列表
     * @return 影响的行数
     */
    public static int update(String table, Map<String, Object> dataMap, List<QueryCondition> conditions) {
        if (dataMap == null || dataMap.isEmpty()) {
            throw new IllegalArgumentException("更新数据不能为空");
        }
        if (conditions == null || conditions.isEmpty()) {
            throw new IllegalArgumentException("更新条件不能为空");
        }

        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE ").append(table).append(" SET ");
        List<Object> params = new ArrayList<>();

        // 构建SET部分
        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
            sql.append(entry.getKey()).append(" = ?,");
            params.add(entry.getValue());
        }
        sql.setLength(sql.length() - 1);

        // 构建WHERE部分
        QueryBuilderResult result = buildWhereClause(conditions);
        sql.append(result.getWhereClause());
        params.addAll(result.getParams());

        return jdbcTemplate.update(sql.toString(), params.toArray());
    }

    /**
     * 根据ID查询单条记录
     * @param table 表名
     * @param id 主键值
     * @return 记录映射
     */
    public static Map<String, Object> findById(String table, Object id) {
        String sql = "SELECT * FROM " + table + " WHERE id = ?";
        try {
            return jdbcTemplate.queryForMap(sql, id);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    /**
     * 查询所有记录
     * @param table 表名
     * @return 记录列表
     */
    public static List<Map<String, Object>> findAll(String table) {
        String sql = "SELECT * FROM " + table;
        return jdbcTemplate.queryForList(sql);
    }



    /**
     * 根据条件查询记录
     * @param table 表名
     * @param conditions 条件列表
     * @return 记录列表
     */
    public static Map<String, Object> findOne(String table, List<QueryCondition> conditions) {
        List<Map<String, Object>> list = find(table, conditions, null, 1);
        return list.isEmpty() ? null : list.get(0);
    }

    /**
     * 根据条件查询记录
     * @param table 表名
     * @param conditions 条件列表
     * @return 记录列表
     */
    public static List<Map<String, Object>> find(String table, List<QueryCondition> conditions) {
        return find(table, conditions, null, null);
    }


    /**
     * 根据条件查询记录（带排序）
     * @param table 表名
     * @param conditions 条件列表
     * @param orderBy 排序字段
     * @return 记录列表
     */
    public static List<Map<String, Object>> find(String table, List<QueryCondition> conditions, String orderBy) {
        return find(table, conditions, orderBy, null);
    }

    /**
     * 根据条件查询记录（带排序和分页）
     * @param table 表名
     * @param conditions 条件列表
     * @param orderBy 排序字段
     * @param limit 限制条数
     * @return 记录列表
     */
    public static List<Map<String, Object>> find(String table, List<QueryCondition> conditions, String orderBy, Integer limit) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT * FROM ").append(table);

        List<Object> params = new ArrayList<>();

        // 构建WHERE条件
        if (conditions != null && !conditions.isEmpty()) {
            QueryBuilderResult result = buildWhereClause(conditions);
            sql.append(result.getWhereClause());
            params.addAll(result.getParams());
        }

        // 添加排序
        if (orderBy != null && !orderBy.trim().isEmpty()) {
            sql.append(" ORDER BY ").append(orderBy);
        }

        // 添加分页
        if (limit != null && limit > 0) {
            sql.append(" LIMIT ").append(limit);
        }

        return jdbcTemplate.queryForList(sql.toString(), params.toArray());
    }

    /**
     * 统计记录数量
     * @param table 表名
     * @param conditions 条件列表
     * @return 记录数量
     */
    public static long count(String table, List<QueryCondition> conditions) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT COUNT(*) FROM ").append(table);

        List<Object> params = new ArrayList<>();

        if (conditions != null && !conditions.isEmpty()) {
            QueryBuilderResult result = buildWhereClause(conditions);
            sql.append(result.getWhereClause());
            params.addAll(result.getParams());
        }

        return jdbcTemplate.queryForObject(sql.toString(), params.toArray(), Long.class);
    }


    public <T> List<T> convertResult(List<Map<String, Object>> list, Class<T> clazz) {
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<Map<String, Object>> data = MappingUtil.mappingToJava(list);
        List<T> result = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();

        for (Map<String, Object> map : data) {
            try {
                T obj = objectMapper.convertValue(map, clazz);
                result.add(obj);
            } catch (Exception e) {
                throw new RuntimeException("Jackson 转换对象失败: " + clazz.getName(), e);
            }
        }

        return result;
    }

    /**
     * 构建WHERE子句
     * @param conditions 条件列表
     * @return 构建结果（包含WHERE子句和参数列表）
     */
    private static QueryBuilderResult buildWhereClause(List<QueryCondition> conditions) {
        StringBuilder whereClause = new StringBuilder();
        List<Object> params = new ArrayList<>();

        whereClause.append(" WHERE ");

        for (int i = 0; i < conditions.size(); i++) {
            QueryCondition condition = conditions.get(i);

            if (i > 0) {
                whereClause.append(" ").append(condition.getLogical()).append(" ");
            }

            whereClause.append(condition.getFieldName()).append(" ").append(condition.getOperator());

            // 处理IN操作符
            if ("IN".equalsIgnoreCase(condition.getOperator())) {
                if (condition.getValue() instanceof Collection) {
                    Collection<?> values = (Collection<?>) condition.getValue();
                    whereClause.append(" (");
                    for (int j = 0; j < values.size(); j++) {
                        whereClause.append("?");
                        if (j < values.size() - 1) {
                            whereClause.append(",");
                        }
                    }
                    whereClause.append(")");
                    params.addAll((Collection<?>) condition.getValue());
                }
            } else {
                whereClause.append(" ?");
                params.add(condition.getValue());
            }
        }

        return new QueryBuilderResult(whereClause.toString(), params);
    }

    /**
     * WHERE子句构建结果类
     */
    private static class QueryBuilderResult {
        private String whereClause;
        private List<Object> params;

        public QueryBuilderResult(String whereClause, List<Object> params) {
            this.whereClause = whereClause;
            this.params = params;
        }

        public String getWhereClause() {
            return whereClause;
        }

        public List<Object> getParams() {
            return params;
        }
    }
}